import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import {
  DropDecorator,
  ContextMenuTriggerDecorator,
} from '@design/desktop/decorator';
import { DraggableCore } from 'react-draggable';
import classNames from 'classnames';
import { isFunction } from '@design/core/utils/is-object';
import intl from 'react-intl-universal';
import './tablecell.less';
import messages from "@i18n/messages";
import pick from 'lodash/pick';
import EN from "@i18n/locales/en";
import CH from "@i18n/locales/zh";
import { isPx } from '../../../utils/is-object';

const locales = {
  en_US: EN,
  zh_CN: CH,
};
    
const validate = (value, limit = 10) => value < limit ? limit : value;

intl.init({
  currentLocale: "zh_CN",
  locales,
});

class TableCell extends Component {
  state = {
    x: undefined,
    y: undefined,
    width: undefined,
    height: undefined,
  };

  constructor(props) {
    super(props);
    this.ref = React.createRef();
  }

  componentDidMount() {
    if (this.ref.current) {
      const element = ReactDOM.findDOMNode(this.ref.current);
      // 内容实际宽高为 元素宽高减去padding
      this.initialWidth = element.clientWidth - 10;
      this.initialHeight = element.clientHeight - 10;
    }
  }

  onStop = () => {
    const { x, y, width, height } = this.state;
    const { node, editor } = this.props;
    let { style, position } = node;
    if (x) {
      position = position.set('x', x);
    }
    if (y) {
      position = position.set('y', y);
    }
    if (width) {
      style = style.set('width', width);
    }
    if (height) {
      style = style.set('height', height);
    }
    editor.updateNode(node, { style, position });
    this.setState({
      x: undefined,
      y: undefined,
      width: undefined,
      height: undefined,
    });
  };

  onStart = (event, data, direction) => {
    const { node } = this.props;
    const { width, height } = node.style;
    const initialState = {
      x: node.position && node.position.x,
      y: node.position && node.position.y,
      width: isPx(width) ? parseFloat(width, 10) : this.initialWidth,
      height: isPx(height) ? parseFloat(height, 10) : this.initialHeight,
    };
    const properties = {
      top: [ 'height', 'y' ],
      bottom: ['height'],
      left: [ 'width', 'x' ],
      right: ['width'],
      topLeft: [ 'height', 'width', 'x', 'y' ],
      topRight: [ 'height', 'width', 'y' ],
      bottomLeft: [ 'height', 'width', 'x' ],
      bottomRight: [ 'height', 'width' ],
    };
    this.setState({
      ...pick(initialState, properties[direction]),
    });
  };

  onResize = (event, data, direction) => {
    event.preventDefault();
    event.stopPropagation();
    switch (direction) {
      case 'top':
        this.setState(({ y, height }) => ({
          y: height <= 10 ? y : validate(y + data.deltaY),
          height: validate(height - data.deltaY),
        }));
        break;
      case 'bottom':
        this.setState(({ height }) => ({
          height: validate(height + data.deltaY),
        }));
        break;
      case 'left':
        this.setState(({ x, width }) => ({
          x: width <= 10 ? x : validate(x + data.deltaX),
          width: validate(width - data.deltaX),
        }));
        break;
      case 'right':
        this.setState(({ width }) => ({
          width: validate(width + data.deltaX),
        }));
        break;
      case 'topLeft':
        this.setState(({ x, y, width, height }) => ({
          x: validate(x + data.deltaX),
          width: validate(width - data.deltaX),
          y: validate(y + data.deltaY),
          height: validate(height - data.deltaY),
        }));
        break;
      case 'topRight':
        this.setState(({ y, width, height }) => ({
          width: validate(width + data.deltaX),
          y: validate(y + data.deltaY),
          height: validate(height - data.deltaY),
        }));
        break;
      case 'bottomRight':
        this.setState(({ width, height }) => ({
          width: validate(width + data.deltaX),
          height: validate(height + data.deltaY),
        }));
        break;
      case 'bottomLeft':
        this.setState(({ x, width, height }) => ({
          x: validate(x + data.deltaX),
          width: validate(width - data.deltaX),
          height: validate(height + data.deltaY),
        }));
        break;
      default:
        break;
    }
  };

  onEdit = () => {
    const { editor, node } = this.props;
    if (editor.showPropertyEditor) {
      editor.showPropertyEditor(node);
    }
  };

  renderResizer = (
    direction = [
      // 'top',
      // 'bottom',
      // 'left',
      // 'right',
      // 'topLeft',
      // 'topRight',
      // 'bottomLeft',
      // 'bottomRight',
    ]
  ) => {
    const width = 8;
    const height = 8;
    const styles = {
      base: {
        position: 'absolute',
        border: '1px solid #3b97e3',
        width,
        height,
        backgroundColor: 'white',
      },
      top: {
        top: 0,
        left: 0,
        right: 0,
        cursor: 'ns-resize',
        margin: `-${height / 2}px auto`,
      },
      bottom: {
        bottom: 0,
        left: 0,
        right: 0,
        cursor: 'ns-resize',
        margin: `-${height / 2}px auto`,
      },
      left: {
        left: 0,
        top: 0,
        bottom: 0,
        cursor: 'w-resize',
        margin: `auto -${width / 2}px`,
      },
      right: {
        right: 0,
        top: 0,
        bottom: 0,
        cursor: 'e-resize',
        margin: `auto -${width / 2}px`,
      },
      topLeft: {
        top: -height / 2,
        left: -width / 2,
        cursor: 'nw-resize',
      },
      topRight: {
        top: -height / 2,
        right: -width / 2,
        cursor: 'ne-resize',
      },
      bottomLeft: {
        bottom: -height / 2,
        left: -width / 2,
        cursor: 'sw-resize',
      },
      bottomRight: {
        bottom: -height / 2,
        right: -width / 2,
        cursor: 'se-resize',
      },
    };
    if (Array.isArray(direction)) {
      return direction.map(this.renderResizer);
    }
    return (
      <DraggableCore
        onDrag={(event, data) => this.onResize(event, data, direction)}
        onStart={(event, data) => this.onStart(event, data, direction)}
        onStop={(event, data) => this.onStop(event, data, direction)}
        key={direction}
      >
        <div style={{ ...styles.base, ...styles[direction] }} />
      </DraggableCore>
    );
  };

  render() {
    const {
      children,
      connectDropTarget,
      renderMenuTrigger,
      attributes,
      isSelected,
      node,
    } = this.props;
    const className = classNames('block', {
      selected: isSelected,
    });
    let content = (
      <td
        {...attributes} className={className}
        ref={this.ref}
        onClick={this.onEdit}
        style={{ position: 'relative', ...node.style.toJS() }}
      >
        {isSelected && this.renderResizer()}
        {isFunction(renderMenuTrigger) ? renderMenuTrigger(children) : children}
      </td>
    );
    if (isFunction(connectDropTarget)) {
      content = connectDropTarget(content);
    }

    return content;
  }
}
const menus = [
  {
    key: 'insertRow',
    title: intl.get(messages.containerComponent.table.row.insert.id),
    action: ({ editor, node }) => {
      editor.insertTableRow(node);
    },
  },
  {
    key: 'insertCell',
    title: intl.get(messages.containerComponent.table.cell.insert.id),
    action: ({ editor, node }) => {
      editor.insertTableCell(node);
    },
  },
  {
    key: 'deleteRow',
    title: intl.get(messages.containerComponent.table.row.delete.id),
    action: ({ editor, node }) => {
      editor.deleteTableRow(node);
    },
  },
  {
    key: 'deleteCell',
    title: intl.get(messages.containerComponent.table.cell.delete.id),
    action: ({ editor, node }) => {
      editor.deleteTableCell(node);
    },
  },
];
const DropTableCell = DropDecorator()(TableCell);
TableCell.DropTableCell = ContextMenuTriggerDecorator({ menus })(DropTableCell);
export default TableCell;
